/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.schedule;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.control.Threadx;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Threads;

/**
 * 使用线程实现一个单一的定时任务 <br><br>
 * 
 * 注意:该Interval的线程处理完后再sleep <br><br>
 * 该类的使用场景为：
 *      1）定时触发要求不严格 <br>
 *      2）不作时间追赶,不与系统时间比较 <br>
 *      3）该类的指Task类名为Timer线程名 <br>
 *      4）该类仅支持一个Task <br>
 *      
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Interval")
public class Interval extends Threadx implements SignConstants
{
    private static final Log log = LogFactory.getLog(Interval.class);
    
    private volatile int times;
    
    private Task task;
    private String taskName;
    
    private int firstMillis;
    private int middleMillis;
    
    /********************************************************************************/
    //提交任务的定时安排 静态方法
    /********************************************************************************/
    
    /** 创建Interval，仅运行一次任务 */
    public static Interval one(Task task)
    {
        return new Interval().open(task, 0, 0, 1);
    }
    
    /**
     * 创建Interval，支持传入任务，每次等待时间，启动立即运行，默认一直运行
     * 
     * @param task              任务
     * @param millis            每次等待时间毫秒数
     */
    public static Interval shedule(Task task, int millis)
    {
        return new Interval().open(task, 0, millis, _INFINITE_);
    }
    
    /**
     * 创建Interval，支持传入任务，时间参数，默认一直运行
     * 
     * @param task              任务
     * @param firstMillis       第一次等待时间毫秒数
     * @param middleMillis      每次等待时间毫秒数
     */
    public static Interval shedule(Task task, int firstMillis, int middleMillis)
    {
        return new Interval().open(task, firstMillis, middleMillis, _INFINITE_);
    }
    
    /**
     * 创建Interval，支持传入任务，时间参数和次数
     * 
     * @param task              任务
     * @param firstMillis       第一次等待时间毫秒数
     * @param middleMillis      每次等待时间毫秒数
     * @param times             执行次数
     */
    public static Interval shedule(Task task, int firstMillis, int middleMillis, int times)
    {
        return new Interval().open(task, firstMillis, middleMillis, times);
    }
    
    /********************************************************************************/
    //提交任务的定时安排 静态方法
    /********************************************************************************/
    
    /** 设置任务 */
    public Interval open(Task task, int firstMillis, int middleMillis, int times)
    {
        this.task = task;
        this.taskName = Strings.removeLeftByLast(task.getClass().getName(), ".");
        
        this.firstMillis = firstMillis;
        this.middleMillis = middleMillis;
        this.times = times;
        
        super.open();
        return this;
    }
    
    /** 获取任务对象 */
    public Task getTask()
    {
        return task;
    }
    
    /*****************************************************************/
    //线程名和关闭操作
    /*****************************************************************/
    
    @Override /** 线程名 */
    public String getThreadName()
    {
        return _INTERVAL_ + "-" + taskName;
    }
    
    @Override /** 线程关闭后 */
    public void closeAfter()
    {
        this.times = 0;
    }
    
    /*****************************************************************/
    //任务操作
    /*****************************************************************/
    
    @Override /** 线程首次运行 */
    protected void first()
    {
        if (task instanceof TaskLoad)
        {//有加载要求的任务，前置加载
            ((TaskLoad)task).load();
        }
        
        //首次等待时长
        Threads.sleepIgnoreException(firstMillis);
    }
    
    @Override /** 线程持续运行 */
    protected void loop()
    {
        if (times == 0)
        {//执行次数到达
            close();
            return;
        }
        
        try
        {
            task.execute();
        }
        catch(Throwable e)
        {
            if (times == _INFINITE_)
                log.error("Interval:[%s],运行时异常", e, getThreadName());
            else
                log.error("Interval:[%s],运行时%s异常", e, getThreadName(), ((times == _INFINITE_)?"":"[第"+times+"次]"));
        }
        
        if (times > 0)
            times--;
        
        Threads.sleepIgnoreException(middleMillis);
    }
    
    @Override
    public String toString()
    {
        return new StringBuilder("{name:Interval, ")
            .append("firstMillis:").append(firstMillis).append(", ")
            .append("middleMillis:").append(middleMillis).append(", ")
            .append("times:").append(times).append("}")
            .toString();
    }
}
